package com.myKng.shareservice.service.impl;

import com.myKng.shareservice.dto.ShareLinkRequest;
import com.myKng.shareservice.dto.ShareLinkResponse;
import com.myKng.shareservice.exception.ResourceNotFoundException;
import com.myKng.shareservice.exception.UnauthorizedException;
import com.myKng.shareservice.model.AccessType;
import com.myKng.shareservice.model.ShareLink;
import com.myKng.shareservice.repository.ShareLinkRepository;
import com.myKng.shareservice.service.ShareService;
import com.myKng.shareservice.util.ShareCodeGenerator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 分享服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ShareServiceImpl implements ShareService {

    private final ShareLinkRepository shareLinkRepository;
    private final ShareCodeGenerator shareCodeGenerator;

    @Value("${share.base-url:http://localhost:8084/api/share/}")
    private String shareBaseUrl;

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    @Transactional
    public ShareLinkResponse createShareLink(ShareLinkRequest request, Long creatorId) {
        // 验证请求参数
        validateShareLinkRequest(request);

        // 生成唯一分享码
        String shareCode = shareCodeGenerator.generateUniqueCode();

        // 创建分享链接实体
        ShareLink shareLink = ShareLink.builder()
                .shareCode(shareCode)
                .contentId(request.getContentId())
                .contentType(request.getContentType())
                .creatorId(creatorId)
                .title(request.getTitle())
                .description(request.getDescription())
                .accessType(request.getAccessType())
                .accessPassword(request.getAccessPassword())
                .expiryTime(request.getExpiryTime())
                .maxAccessCount(request.getMaxAccessCount() != null ? request.getMaxAccessCount() : 0)
                .accessCount(0)
                .enabled(true)
                .build();

        // 保存分享链接
        ShareLink savedShareLink = shareLinkRepository.save(shareLink);
        log.info("Created share link with code: {}", shareCode);

        // 转换为响应DTO
        return convertToShareLinkResponse(savedShareLink);
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    public ShareLinkResponse getShareLinkByCode(String shareCode) {
        ShareLink shareLink = getShareLinkEntityByCode(shareCode);
        return convertToShareLinkResponse(shareLink);
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    public boolean verifyShareLinkAccess(String shareCode, String password, Long userId) {
        ShareLink shareLink = getShareLinkEntityByCode(shareCode);

        // 检查分享链接是否已禁用
        if (!shareLink.getEnabled()) {
            log.warn("Attempted to access disabled share link: {}", shareCode);
            return false;
        }

        // 检查是否过期
        if (isShareLinkExpired(shareLink)) {
            log.warn("Attempted to access expired share link: {}", shareCode);
            return false;
        }

        // 检查访问次数是否超限
        if (shareLink.getMaxAccessCount() > 0 && shareLink.getAccessCount() >= shareLink.getMaxAccessCount()) {
            log.warn("Attempted to access share link with exceeded access count: {}", shareCode);
            return false;
        }

        // 根据访问类型验证权限
        switch (shareLink.getAccessType()) {
            case PUBLIC:
                return true;
            case PRIVATE:
                return Objects.equals(shareLink.getAccessPassword(), password);
            case RESTRICTED:
                return Objects.equals(shareLink.getCreatorId(), userId);
            default:
                return false;
        }
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    @Transactional
    public ShareLink recordShareLinkAccess(String shareCode) {
        ShareLink shareLink = getShareLinkEntityByCode(shareCode);
        shareLink.setAccessCount(shareLink.getAccessCount() + 1);
        return shareLinkRepository.save(shareLink);
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    public List<ShareLinkResponse> getUserShareLinks(Long creatorId) {
        List<ShareLink> shareLinks = shareLinkRepository.findByCreatorIdOrderByCreatedAtDesc(creatorId);
        return shareLinks.stream()
                .map(this::convertToShareLinkResponse)
                .collect(Collectors.toList());
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    @Transactional
    public boolean disableShareLink(String shareCode, Long creatorId) {
        ShareLink shareLink = getShareLinkEntityByCode(shareCode);

        // 验证创建者权限
        if (!Objects.equals(shareLink.getCreatorId(), creatorId)) {
            log.warn("User {} attempted to disable share link created by user {}", creatorId, shareLink.getCreatorId());
            throw new UnauthorizedException("您没有权限禁用此分享链接");
        }

        shareLink.setEnabled(false);
        shareLinkRepository.save(shareLink);
        log.info("Disabled share link with code: {}", shareCode);
        return true;
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }
    @Transactional
    public ShareLinkResponse updateShareLink(String shareCode, ShareLinkRequest request, Long creatorId) {
        ShareLink shareLink = getShareLinkEntityByCode(shareCode);

        // 验证创建者权限
        if (!Objects.equals(shareLink.getCreatorId(), creatorId)) {
            log.warn("User {} attempted to update share link created by user {}", creatorId, shareLink.getCreatorId());
            throw new UnauthorizedException("您没有权限更新此分享链接");
        }

        // 验证请求参数
        validateShareLinkRequest(request);

        // 更新分享链接
        shareLink.setTitle(request.getTitle());
        shareLink.setDescription(request.getDescription());
        shareLink.setAccessType(request.getAccessType());
        shareLink.setAccessPassword(request.getAccessPassword());
        shareLink.setExpiryTime(request.getExpiryTime());
        shareLink.setMaxAccessCount(request.getMaxAccessCount() != null ? request.getMaxAccessCount() : 0);

        ShareLink updatedShareLink = shareLinkRepository.save(shareLink);
        log.info("Updated share link with code: {}", shareCode);

        return convertToShareLinkResponse(updatedShareLink);
    }

        /**
     * 清理过期和无效的分享链接
     */
    @Override
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    public void cleanupExpiredShareLinks() {
        LocalDateTime now = LocalDateTime.now();
        
        // 清理过期的分享链接
        List<ShareLink> expiredLinks = shareLinkRepository.findByExpiryTimeLessThanAndEnabledTrue(now);
        if (!expiredLinks.isEmpty()) {
            expiredLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(expiredLinks);
            log.info("Disabled {} expired share links", expiredLinks.size());
        }
        
        // 清理访问次数已达上限的分享链接
        List<ShareLink> accessLimitedLinks = shareLinkRepository.findByAccessCountExceeded();
        if (!accessLimitedLinks.isEmpty()) {
            accessLimitedLinks.forEach(link -> link.setEnabled(false));
            shareLinkRepository.saveAll(accessLimitedLinks);
            log.info("Disabled {} share links that reached access limit", accessLimitedLinks.size());
        }
    }
    
    @Override
    public String getShareUrl(String shareCode) {
        return shareBaseUrl + shareCode;
    }
    
    /**
     * 根据分享码获取分享链接实体
     *
     * @param shareCode 分享码
     * @return 分享链接实体
     */
    private ShareLink getShareLinkEntityByCode(String shareCode) {
        return shareLinkRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接不存在或已失效"));
    }
    
    /**
     * 检查分享链接是否已过期
     *
     * @param shareLink 分享链接
     * @return 是否已过期
     */
    private boolean isShareLinkExpired(ShareLink shareLink) {
        return shareLink.getExpiryTime() != null && shareLink.getExpiryTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 验证分享链接请求参数
     *
     * @param request 分享链接请求
     */
    private void validateShareLinkRequest(ShareLinkRequest request) {
        // 如果访问类型为PRIVATE，必须提供密码
        if (AccessType.PRIVATE.equals(request.getAccessType()) && 
            (request.getAccessPassword() == null || request.getAccessPassword().trim().isEmpty())) {
            throw new IllegalArgumentException("私有分享必须设置访问密码");
        }
    }
    
    /**
     * 将分享链接实体转换为响应DTO
     *
     * @param shareLink 分享链接实体
     * @return 分享链接响应DTO
     */
    private ShareLinkResponse convertToShareLinkResponse(ShareLink shareLink) {
        boolean isExpired = isShareLinkExpired(shareLink);
        boolean isPasswordRequired = AccessType.PRIVATE.equals(shareLink.getAccessType());
        
        return ShareLinkResponse.builder()
                .id(shareLink.getId())
                .shareCode(shareLink.getShareCode())
                .shareUrl(getShareUrl(shareLink.getShareCode()))
                .contentId(shareLink.getContentId())
                .contentType(shareLink.getContentType())
                .creatorId(shareLink.getCreatorId())
                .title(shareLink.getTitle())
                .description(shareLink.getDescription())
                .accessType(shareLink.getAccessType())
                .passwordRequired(isPasswordRequired)
                .expiryTime(shareLink.getExpiryTime())
                .accessCount(shareLink.getAccessCount())
                .maxAccessCount(shareLink.getMaxAccessCount())
                .createdAt(shareLink.getCreatedAt())
                .updatedAt(shareLink.getUpdatedAt())
                .enabled(shareLink.getEnabled())
                .expired(isExpired)
                .build();
    }